package wiz.client.activities.selectplayers;

import java.util.ArrayList;
import java.util.List;

import wiz.client.ClientFactory;
import wiz.client.WizIntegration;
import wiz.client.WizStrings;
import wiz.client.activities.entrypoint.EntryPointPlace;
import wiz.client.model.WizGameModel;
import wiz.client.model.WizPlayer;

import com.google.gwt.activity.shared.AbstractActivity;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;

public class SelectPlayersActivity extends AbstractActivity {

	private ClientFactory fClientFactory;
	private SelectPlayersView fView;
	private boolean fSelectionConfirmed;
	private ArrayList<SelectPlayerTableModel> fNames = new ArrayList<SelectPlayerTableModel>();
	private String fGameStateToken;

	private final WizStrings fWizStrings = GWT.create(WizStrings.class);
	private SingleSelectionModel<SelectPlayerTableModel> fSelectionModel;

	
	public SelectPlayersActivity(ClientFactory clientFactory) {
		fClientFactory = clientFactory;
		SelectPlayersView view = fClientFactory.buildSelectPlayersView();
		fView = view;
		initHandlers();
	}

	@Override
	public void start(AcceptsOneWidget panel, EventBus eventBus) {
		panel.setWidget(fView);
		fSelectionConfirmed = false;
		if(fNames.size() > 0){
			//already loaded the list. Use it.
			fView.setTableData(new ListDataProvider<SelectPlayerTableModel>(fNames));
		} else {

			loadPlayerList();				
		}
		Window.scrollTo(0, 0);
	}

	private void loadPlayerList() {
		
		
		
		WizIntegration remoteSystemIntegration = fClientFactory.getRemoteSystemIntegration();
		
		final WizGameModel loadGameState = fGameStateToken != null ? fClientFactory.getGameStateStorage().loadGameState(fGameStateToken) : null;
		
		if(remoteSystemIntegration.canPullPlayerListFromRemoteSystem()){
			remoteSystemIntegration.pullPlayerNames(new AsyncCallback<List<String>>() {

				@Override
				public void onFailure(Throwable caught) {
					fView.setTableData(new ListDataProvider<SelectPlayerTableModel>(fNames));
				}

				@Override
				public void onSuccess(List<String> result) {
					fNames.clear();
					for (String playerName : result) {
						SelectPlayerTableModel selectPlayerTableModel = new SelectPlayerTableModel();
						selectPlayerTableModel.setPlayerName(playerName);
						if (loadGameState != null) {
							for (WizPlayer p : loadGameState.getWizPlayers()) {
								if (p.getName().equals(selectPlayerTableModel.getPlayerName())) {
									selectPlayerTableModel.setPlayerSelected(true);
								}
							}
						}
						fNames.add(selectPlayerTableModel);
					}
					
					addPreviousCustomAddedPlayers(loadGameState);
					
					fView.setTableData(new ListDataProvider<SelectPlayerTableModel>(fNames));
				}
			});
		} else {
			addPreviousCustomAddedPlayers(loadGameState);
			fView.setTableData(new ListDataProvider<SelectPlayerTableModel>(fNames));
		}


	}

	protected void addPreviousCustomAddedPlayers(WizGameModel loadGameState) {
		if(loadGameState != null){
			//if there are any wiz players whose names are not in the names list, add them
			for (WizPlayer player : loadGameState.getWizPlayers()) {
				boolean exists = false;
				for (SelectPlayerTableModel name : fNames) {
					if(name.getPlayerName().equals(player.getName())){
						exists = true;
						break;
					}
				}
				
				if(!exists){
					SelectPlayerTableModel customPlayerModelItem = new SelectPlayerTableModel();
					customPlayerModelItem.setPlayerName(player.getName());
					customPlayerModelItem.setPlayerSelected(true);
					fNames.add(customPlayerModelItem);
				}
			}
		}
	}

	private void initHandlers() {
		fView.getDoneButtonClickHandlers().addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				doneClicked();
			}
		});

		fView.addPlayerSelectionFieldUpdater(new FieldUpdater<SelectPlayerTableModel, Boolean>() {

			@Override
			public void update(int index, SelectPlayerTableModel object, Boolean value) {
//				object.setPlayerSelected(value);
			}
		});
		
		fView.getAddPlayerButton().addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				addPlayerClicked();
			}
		});
		
		fSelectionModel = new SingleSelectionModel<SelectPlayerTableModel>();
		fView.setTableSelectionModel(fSelectionModel);
		fSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
			
			@Override
			public void onSelectionChange(SelectionChangeEvent event) {
				tableSelectionChanged();
			}
		});
	}

	protected void tableSelectionChanged() {
		SelectPlayerTableModel selectedObject = fSelectionModel.getSelectedObject();
		if(selectedObject != null){
			selectedObject.setPlayerSelected(!selectedObject.isPlayerSelected());
			fView.refreshTable();
		}
	}

	protected void addPlayerClicked() {
		String text = fView.getAddPlayerNameText().getText();
		text = text.trim();
		if(text.length() == 0){
			//TODO: Error handling: 
		}
		
		for (SelectPlayerTableModel name : fNames) {
			if(name.getPlayerName().equals(text)){
				//TODO: Error handling
			}
		}
		
		SelectPlayerTableModel newPlayerTableModelItem = new SelectPlayerTableModel();
		newPlayerTableModelItem.setPlayerName(text);
		newPlayerTableModelItem.setPlayerSelected(true);
		fNames.add(newPlayerTableModelItem);
		
		fView.setTableData(new ListDataProvider<SelectPlayerTableModel>(fNames));
		
		fView.getAddPlayerNameText().setText(""); //$NON-NLS-1$
	}

	@Override
	public String mayStop() {
		if (!fSelectionConfirmed) {
			return fWizStrings.notConfirmedPlayerSelection();
		} else
			return null;
	}

	protected void doneClicked() {
		fSelectionConfirmed = true;

		WizGameModel wizGameModel = null;
		
		if(fGameStateToken != null){
			wizGameModel = fClientFactory.getGameStateStorage().loadGameState(fGameStateToken);
		}
		
		if(wizGameModel == null){
			wizGameModel = fClientFactory.getWizModelFactory().createModel();
		}
		
		List<WizPlayer> players = wizGameModel.getWizPlayers();
		players.clear();
		for (SelectPlayerTableModel wizPlayer : fNames) {
			if (wizPlayer.isPlayerSelected()) {
				WizPlayer wizPlayerToAdd = fClientFactory.getWizModelFactory().createPlayer();
				wizPlayerToAdd.setName(wizPlayer.getPlayerName());
				players.add(wizPlayerToAdd);
			}
		}

		fClientFactory.getPlaceController().goTo(new EntryPointPlace(fClientFactory.getGameStateStorage().storeGameState(wizGameModel)));
	}

	public void setGameStateToken(String gameStateToken) {
		fGameStateToken = gameStateToken;
	}

}
